/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. *//* * Internal PKCS #11 functions. Should only be called by pkcs11.c */#include"pkcs11.h"#include"lgdb.h"#include"pcertt.h"#include"lowkeyi.h"#include"pcert.h"#include"blapi.h"#include"secerr.h"#include"secasn1.h"/* * Cache the object we are working on during Set's and Get's */typedefstructLGObjectCacheStr{CK_OBJECT_CLASSobjclass;CK_OBJECT_HANDLEhandle;SDB*sdb;void*objectInfo;LGFreeFuncinfoFree;SECItemdbKey;}LGObjectCache;staticconstCK_OBJECT_HANDLElg_classArray[]={0,CKO_PRIVATE_KEY,CKO_PUBLIC_KEY,CKO_SECRET_KEY,CKO_NSS_TRUST,CKO_NSS_CRL,CKO_NSS_SMIME,CKO_CERTIFICATE};#define handleToClass(handle) \ lg_classArray[((handle & LG_TOKEN_TYPE_MASK)) >> LG_TOKEN_TYPE_SHIFT]staticvoidlg_DestroyObjectCache(LGObjectCache*obj);staticLGObjectCache*lg_NewObjectCache(SDB*sdb,constSECItem*dbKey,CK_OBJECT_HANDLEhandle){LGObjectCache*obj=NULL;SECStatusrv;obj=PORT_New(LGObjectCache);if(obj==NULL){returnNULL;}obj->objclass=handleToClass(handle);obj->handle=handle;obj->sdb=sdb;obj->objectInfo=NULL;obj->infoFree=NULL;obj->dbKey.data=NULL;obj->dbKey.len=0;lg_DBLock(sdb);if(dbKey==NULL){dbKey=lg_lookupTokenKeyByHandle(sdb,handle);}if(dbKey==NULL){lg_DBUnlock(sdb);gotoloser;}rv=SECITEM_CopyItem(NULL,&obj->dbKey,dbKey);lg_DBUnlock(sdb);if(rv!=SECSuccess){gotoloser;}returnobj;loser:(void)lg_DestroyObjectCache(obj);returnNULL;}/* * free all the data associated with an object. Object reference count must * be 'zero'. */staticvoidlg_DestroyObjectCache(LGObjectCache*obj){if(obj->dbKey.data){PORT_Free(obj->dbKey.data);obj->dbKey.data=NULL;}if(obj->objectInfo){(*obj->infoFree)(obj->objectInfo);obj->objectInfo=NULL;obj->infoFree=NULL;}PORT_Free(obj);}/* * ******************** Attribute Utilities ******************************* */staticCK_RVlg_ULongAttribute(CK_ATTRIBUTE*attr,CK_ATTRIBUTE_TYPEtype,CK_ULONGvalue){unsignedchar*data;inti;if(attr->pValue==NULL){attr->ulValueLen=4;returnCKR_OK;}if(attr->ulValueLen<4){attr->ulValueLen=(CK_ULONG)-1;returnCKR_BUFFER_TOO_SMALL;}data=(unsignedchar*)attr->pValue;for(i=0;i<4;i++){data[i]=(value>>((3-i)*8))&0xff;}attr->ulValueLen=4;returnCKR_OK;}staticCK_RVlg_CopyAttribute(CK_ATTRIBUTE*attr,CK_ATTRIBUTE_TYPEtype,CK_VOID_PTRvalue,CK_ULONGlen){if(attr->pValue==NULL){attr->ulValueLen=len;returnCKR_OK;}if(attr->ulValueLen<len){attr->ulValueLen=(CK_ULONG)-1;returnCKR_BUFFER_TOO_SMALL;}if(value!=NULL){PORT_Memcpy(attr->pValue,value,len);}attr->ulValueLen=len;returnCKR_OK;}staticCK_RVlg_CopyAttributeSigned(CK_ATTRIBUTE*attribute,CK_ATTRIBUTE_TYPEtype,void*value,CK_ULONGlen){unsignedchar*dval=(unsignedchar*)value;if(*dval==0){dval++;len--;}returnlg_CopyAttribute(attribute,type,dval,len);}staticCK_RVlg_CopyPrivAttribute(CK_ATTRIBUTE*attribute,CK_ATTRIBUTE_TYPEtype,void*value,CK_ULONGlen,SDB*sdbpw){SECItemplainText,*cipherText=NULL;CK_RVcrv=CKR_USER_NOT_LOGGED_IN;SECStatusrv;plainText.data=value;plainText.len=len;rv=lg_util_encrypt(NULL,sdbpw,&plainText,&cipherText);if(rv!=SECSuccess){gotoloser;}crv=lg_CopyAttribute(attribute,type,cipherText->data,cipherText->len);loser:if(cipherText){SECITEM_FreeItem(cipherText,PR_TRUE);}returncrv;}staticCK_RVlg_CopyPrivAttrSigned(CK_ATTRIBUTE*attribute,CK_ATTRIBUTE_TYPEtype,void*value,CK_ULONGlen,SDB*sdbpw){unsignedchar*dval=(unsignedchar*)value;if(*dval==0){dval++;len--;}returnlg_CopyPrivAttribute(attribute,type,dval,len,sdbpw);}staticCK_RVlg_invalidAttribute(CK_ATTRIBUTE*attr){attr->ulValueLen=(CK_ULONG)-1;returnCKR_ATTRIBUTE_TYPE_INVALID;}#define LG_DEF_ATTRIBUTE(value, len) \ { \ 0, value, len \ }#define LG_CLONE_ATTR(attribute, type, staticAttr) \ lg_CopyAttribute(attribute, type, staticAttr.pValue, staticAttr.ulValueLen)CK_BBOOLlg_staticTrueValue=CK_TRUE;CK_BBOOLlg_staticFalseValue=CK_FALSE;staticconstCK_ATTRIBUTElg_StaticTrueAttr=LG_DEF_ATTRIBUTE(&lg_staticTrueValue,sizeof(lg_staticTrueValue));staticconstCK_ATTRIBUTElg_StaticFalseAttr=LG_DEF_ATTRIBUTE(&lg_staticFalseValue,sizeof(lg_staticFalseValue));staticconstCK_ATTRIBUTElg_StaticNullAttr=LG_DEF_ATTRIBUTE(NULL,0);charlg_StaticOneValue=1;/* * helper functions which get the database and call the underlying * low level database function. */staticchar*lg_FindKeyNicknameByPublicKey(SDB*sdb,SECItem*dbKey){NSSLOWKEYDBHandle*keyHandle;char*label;keyHandle=lg_getKeyDB(sdb);if(!keyHandle){returnNULL;}label=nsslowkey_FindKeyNicknameByPublicKey(keyHandle,dbKey,sdb);returnlabel;}NSSLOWKEYPrivateKey*lg_FindKeyByPublicKey(SDB*sdb,SECItem*dbKey){NSSLOWKEYPrivateKey*privKey;NSSLOWKEYDBHandle*keyHandle;keyHandle=lg_getKeyDB(sdb);if(keyHandle==NULL){returnNULL;}privKey=nsslowkey_FindKeyByPublicKey(keyHandle,dbKey,sdb);if(privKey==NULL){returnNULL;}returnprivKey;}staticcertDBEntrySMime*lg_getSMime(LGObjectCache*obj){certDBEntrySMime*entry;NSSLOWCERTCertDBHandle*certHandle;if(obj->objclass!=CKO_NSS_SMIME){returnNULL;}if(obj->objectInfo){return(certDBEntrySMime*)obj->objectInfo;}certHandle=lg_getCertDB(obj->sdb);if(!certHandle){returnNULL;}entry=nsslowcert_ReadDBSMimeEntry(certHandle,(char*)obj->dbKey.data);obj->objectInfo=(void*)entry;obj->infoFree=(LGFreeFunc)nsslowcert_DestroyDBEntry;returnentry;}staticcertDBEntryRevocation*lg_getCrl(LGObjectCache*obj){certDBEntryRevocation*crl;PRBoolisKrl;NSSLOWCERTCertDBHandle*certHandle;if(obj->objclass!=CKO_NSS_CRL){returnNULL;}if(obj->objectInfo){return(certDBEntryRevocation*)obj->objectInfo;}isKrl=(PRBool)(obj->handle==LG_TOKEN_KRL_HANDLE);certHandle=lg_getCertDB(obj->sdb);if(!certHandle){returnNULL;}crl=nsslowcert_FindCrlByKey(certHandle,&obj->dbKey,isKrl);obj->objectInfo=(void*)crl;obj->infoFree=(LGFreeFunc)nsslowcert_DestroyDBEntry;returncrl;}staticNSSLOWCERTCertificate*lg_getCert(LGObjectCache*obj,NSSLOWCERTCertDBHandle*certHandle){NSSLOWCERTCertificate*cert;CK_OBJECT_CLASSobjClass=obj->objclass;if((objClass!=CKO_CERTIFICATE)&&(objClass!=CKO_NSS_TRUST)){returnNULL;}if(objClass==CKO_CERTIFICATE&&obj->objectInfo){return(NSSLOWCERTCertificate*)obj->objectInfo;}cert=nsslowcert_FindCertByKey(certHandle,&obj->dbKey);if(objClass==CKO_CERTIFICATE){obj->objectInfo=(void*)cert;obj->infoFree=(LGFreeFunc)nsslowcert_DestroyCertificate;}returncert;}staticNSSLOWCERTTrust*lg_getTrust(LGObjectCache*obj,NSSLOWCERTCertDBHandle*certHandle){NSSLOWCERTTrust*trust;if(obj->objclass!=CKO_NSS_TRUST){returnNULL;}if(obj->objectInfo){return(NSSLOWCERTTrust*)obj->objectInfo;}trust=nsslowcert_FindTrustByKey(certHandle,&obj->dbKey);obj->objectInfo=(void*)trust;obj->infoFree=(LGFreeFunc)nsslowcert_DestroyTrust;returntrust;}staticNSSLOWKEYPublicKey*lg_GetPublicKey(LGObjectCache*obj){NSSLOWKEYPublicKey*pubKey;NSSLOWKEYPrivateKey*privKey;if(obj->objclass!=CKO_PUBLIC_KEY){returnNULL;}if(obj->objectInfo){return(NSSLOWKEYPublicKey*)obj->objectInfo;}privKey=lg_FindKeyByPublicKey(obj->sdb,&obj->dbKey);if(privKey==NULL){returnNULL;}pubKey=lg_nsslowkey_ConvertToPublicKey(privKey);lg_nsslowkey_DestroyPrivateKey(privKey);obj->objectInfo=(void*)pubKey;obj->infoFree=(LGFreeFunc)lg_nsslowkey_DestroyPublicKey;returnpubKey;}/* * we need two versions of lg_GetPrivateKey. One version that takes the * DB handle so we can pass the handle we have already acquired in, * rather than going through the 'getKeyDB' code again, * which may fail the second time and another which just aquires * the key handle from the sdb (where we don't already have a key handle. * This version does the former. */staticNSSLOWKEYPrivateKey*lg_GetPrivateKeyWithDB(LGObjectCache*obj,NSSLOWKEYDBHandle*keyHandle){NSSLOWKEYPrivateKey*privKey;if((obj->objclass!=CKO_PRIVATE_KEY)&&(obj->objclass!=CKO_SECRET_KEY)){returnNULL;}if(obj->objectInfo){return(NSSLOWKEYPrivateKey*)obj->objectInfo;}privKey=nsslowkey_FindKeyByPublicKey(keyHandle,&obj->dbKey,obj->sdb);if(privKey==NULL){returnNULL;}obj->objectInfo=(void*)privKey;obj->infoFree=(LGFreeFunc)lg_nsslowkey_DestroyPrivateKey;returnprivKey;}/* this version does the latter */staticNSSLOWKEYPrivateKey*lg_GetPrivateKey(LGObjectCache*obj){NSSLOWKEYDBHandle*keyHandle;NSSLOWKEYPrivateKey*privKey;keyHandle=lg_getKeyDB(obj->sdb);if(!keyHandle){returnNULL;}privKey=lg_GetPrivateKeyWithDB(obj,keyHandle);returnprivKey;}/* lg_GetPubItem returns data associated with the public key. * one only needs to free the public key. This comment is here * because this sematic would be non-obvious otherwise. All callers * should include this comment. */staticSECItem*lg_GetPubItem(NSSLOWKEYPublicKey*pubKey){SECItem*pubItem=NULL;/* get value to compare from the cert's public key */switch(pubKey->keyType){caseNSSLOWKEYRSAKey:pubItem=&pubKey->u.rsa.modulus;break;caseNSSLOWKEYDSAKey:pubItem=&pubKey->u.dsa.publicValue;break;caseNSSLOWKEYDHKey:pubItem=&pubKey->u.dh.publicValue;break;#ifndef NSS_DISABLE_ECCcaseNSSLOWKEYECKey:pubItem=&pubKey->u.ec.publicValue;break;#endif /* NSS_DISABLE_ECC */default:break;}returnpubItem;}staticCK_RVlg_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey*key,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute){unsignedcharhash[SHA1_LENGTH];CK_KEY_TYPEkeyType=CKK_RSA;switch(type){caseCKA_KEY_TYPE:returnlg_ULongAttribute(attribute,type,keyType);caseCKA_ID:SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);returnlg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);caseCKA_DERIVE:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_ENCRYPT:caseCKA_VERIFY:caseCKA_VERIFY_RECOVER:caseCKA_WRAP:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_MODULUS:returnlg_CopyAttributeSigned(attribute,type,key->u.rsa.modulus.data,key->u.rsa.modulus.len);caseCKA_PUBLIC_EXPONENT:returnlg_CopyAttributeSigned(attribute,type,key->u.rsa.publicExponent.data,key->u.rsa.publicExponent.len);default:break;}returnlg_invalidAttribute(attribute);}staticCK_RVlg_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey*key,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute){unsignedcharhash[SHA1_LENGTH];CK_KEY_TYPEkeyType=CKK_DSA;switch(type){caseCKA_KEY_TYPE:returnlg_ULongAttribute(attribute,type,keyType);caseCKA_ID:SHA1_HashBuf(hash,key->u.dsa.publicValue.data,key->u.dsa.publicValue.len);returnlg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);caseCKA_DERIVE:caseCKA_ENCRYPT:caseCKA_VERIFY_RECOVER:caseCKA_WRAP:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_VERIFY:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_VALUE:returnlg_CopyAttributeSigned(attribute,type,key->u.dsa.publicValue.data,key->u.dsa.publicValue.len);caseCKA_PRIME:returnlg_CopyAttributeSigned(attribute,type,key->u.dsa.params.prime.data,key->u.dsa.params.prime.len);caseCKA_SUBPRIME:returnlg_CopyAttributeSigned(attribute,type,key->u.dsa.params.subPrime.data,key->u.dsa.params.subPrime.len);caseCKA_BASE:returnlg_CopyAttributeSigned(attribute,type,key->u.dsa.params.base.data,key->u.dsa.params.base.len);default:break;}returnlg_invalidAttribute(attribute);}staticCK_RVlg_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey*key,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute){unsignedcharhash[SHA1_LENGTH];CK_KEY_TYPEkeyType=CKK_DH;switch(type){caseCKA_KEY_TYPE:returnlg_ULongAttribute(attribute,type,keyType);caseCKA_ID:SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);returnlg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);caseCKA_DERIVE:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_ENCRYPT:caseCKA_VERIFY:caseCKA_VERIFY_RECOVER:caseCKA_WRAP:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_VALUE:returnlg_CopyAttributeSigned(attribute,type,key->u.dh.publicValue.data,key->u.dh.publicValue.len);caseCKA_PRIME:returnlg_CopyAttributeSigned(attribute,type,key->u.dh.prime.data,key->u.dh.prime.len);caseCKA_BASE:returnlg_CopyAttributeSigned(attribute,type,key->u.dh.base.data,key->u.dh.base.len);default:break;}returnlg_invalidAttribute(attribute);}#ifndef NSS_DISABLE_ECCstaticCK_RVlg_FindECPublicKeyAttribute(NSSLOWKEYPublicKey*key,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute){unsignedcharhash[SHA1_LENGTH];CK_KEY_TYPEkeyType=CKK_EC;switch(type){caseCKA_KEY_TYPE:returnlg_ULongAttribute(attribute,type,keyType);caseCKA_ID:SHA1_HashBuf(hash,key->u.ec.publicValue.data,key->u.ec.publicValue.len);returnlg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);caseCKA_DERIVE:caseCKA_VERIFY:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_ENCRYPT:caseCKA_VERIFY_RECOVER:caseCKA_WRAP:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_EC_PARAMS:returnlg_CopyAttributeSigned(attribute,type,key->u.ec.ecParams.DEREncoding.data,key->u.ec.ecParams.DEREncoding.len);caseCKA_EC_POINT:if(PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT")){returnlg_CopyAttributeSigned(attribute,type,key->u.ec.publicValue.data,key->u.ec.publicValue.len);}else{SECItem*pubValue=SEC_ASN1EncodeItem(NULL,NULL,&(key->u.ec.publicValue),SEC_ASN1_GET(SEC_OctetStringTemplate));CK_RVcrv;if(!pubValue){returnCKR_HOST_MEMORY;}crv=lg_CopyAttributeSigned(attribute,type,pubValue->data,pubValue->len);SECITEM_FreeItem(pubValue,PR_TRUE);returncrv;}default:break;}returnlg_invalidAttribute(attribute);}#endif /* NSS_DISABLE_ECC */staticCK_RVlg_FindPublicKeyAttribute(LGObjectCache*obj,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute){NSSLOWKEYPublicKey*key;CK_RVcrv;char*label;switch(type){caseCKA_PRIVATE:caseCKA_SENSITIVE:caseCKA_ALWAYS_SENSITIVE:caseCKA_NEVER_EXTRACTABLE:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_MODIFIABLE:caseCKA_EXTRACTABLE:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_SUBJECT:returnLG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);caseCKA_START_DATE:caseCKA_END_DATE:returnLG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);caseCKA_LABEL:label=lg_FindKeyNicknameByPublicKey(obj->sdb,&obj->dbKey);if(label==NULL){returnLG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);}crv=lg_CopyAttribute(attribute,type,label,PORT_Strlen(label));PORT_Free(label);returncrv;default:break;}key=lg_GetPublicKey(obj);if(key==NULL){if(type==CKA_ID){returnLG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);}returnCKR_OBJECT_HANDLE_INVALID;}switch(key->keyType){caseNSSLOWKEYRSAKey:returnlg_FindRSAPublicKeyAttribute(key,type,attribute);caseNSSLOWKEYDSAKey:returnlg_FindDSAPublicKeyAttribute(key,type,attribute);caseNSSLOWKEYDHKey:returnlg_FindDHPublicKeyAttribute(key,type,attribute);#ifndef NSS_DISABLE_ECCcaseNSSLOWKEYECKey:returnlg_FindECPublicKeyAttribute(key,type,attribute);#endif /* NSS_DISABLE_ECC */default:break;}returnlg_invalidAttribute(attribute);}staticCK_RVlg_FindSecretKeyAttribute(LGObjectCache*obj,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute){NSSLOWKEYPrivateKey*key;char*label;unsignedchar*keyString;CK_RVcrv;intkeyTypeLen;CK_ULONGkeyLen;CK_KEY_TYPEkeyType;PRUint32keyTypeStorage;switch(type){caseCKA_PRIVATE:caseCKA_SENSITIVE:caseCKA_ALWAYS_SENSITIVE:caseCKA_EXTRACTABLE:caseCKA_DERIVE:caseCKA_ENCRYPT:caseCKA_DECRYPT:caseCKA_SIGN:caseCKA_VERIFY:caseCKA_WRAP:caseCKA_UNWRAP:caseCKA_MODIFIABLE:caseCKA_LOCAL:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_NEVER_EXTRACTABLE:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_START_DATE:caseCKA_END_DATE:returnLG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);caseCKA_LABEL:label=lg_FindKeyNicknameByPublicKey(obj->sdb,&obj->dbKey);if(label==NULL){returnLG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);}crv=lg_CopyAttribute(attribute,type,label,PORT_Strlen(label));PORT_Free(label);returncrv;caseCKA_ID:returnlg_CopyAttribute(attribute,type,obj->dbKey.data,obj->dbKey.len);caseCKA_KEY_TYPE:caseCKA_VALUE_LEN:caseCKA_VALUE:break;default:returnlg_invalidAttribute(attribute);}key=lg_GetPrivateKey(obj);if(key==NULL){returnCKR_OBJECT_HANDLE_INVALID;}switch(type){caseCKA_KEY_TYPE:/* handle legacy databases. In legacy databases key_type was stored * in host order, with any leading zeros stripped off. Only key types * under 0x1f (AES) were stored. We assume that any values which are * either 1 byte long (big endian), or have byte[0] between 0 and * 0x7f and bytes[1]-bytes[3] equal to '0' (little endian). All other * values are assumed to be from the new database, which is always 4 * bytes in network order */keyType=0;keyString=key->u.rsa.coefficient.data;keyTypeLen=key->u.rsa.coefficient.len;/* * Because of various endian and word lengths The database may have * stored the keyType value in one of the following formats: * (kt) <= 0x1f * length data * Big Endian, pre-3.9, all lengths: 1 (kt) * Little Endian, pre-3.9, 32 bits: 4 (kt) 0 0 0 * Little Endian, pre-3.9, 64 bits: 8 (kt) 0 0 0 0 0 0 0 * All platforms, 3.9, 32 bits: 4 0 0 0 (kt) * Big Endian, 3.9, 64 bits: 8 0 0 0 (kt) 0 0 0 0 * Little Endian, 3.9, 64 bits: 8 0 0 0 0 0 0 0 (kt) * All platforms, >= 3.9.1, all lengths: 4 (a) k1 k2 k3 * where (a) is 0 or >= 0x80. currently (a) can only be 0. *//* * this key was written on a 64 bit platform with a using NSS 3.9 * or earlier. Reduce the 64 bit possibilities above. When we are * through, we will only have: * * Big Endian, pre-3.9, all lengths: 1 (kt) * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0 * All platforms, 3.9, all lengths: 4 0 0 0 (kt) * All platforms, => 3.9.1, all lengths: 4 (a) k1 k2 k3 */if(keyTypeLen==8){keyTypeStorage=*(PRUint32*)keyString;if(keyTypeStorage==0){keyString+=sizeof(PRUint32);}keyTypeLen=4;}/* * Now Handle: * * All platforms, 3.9, all lengths: 4 0 0 0 (kt) * All platforms, => 3.9.1, all lengths: 4 (a) k1 k2 k3 * * NOTE: if kt == 0 or ak1k2k3 == 0, the test fails and * we handle it as: * * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0 */if(keyTypeLen==sizeof(keyTypeStorage)&&(((keyString[0]&0x80)==0x80)||!((keyString[1]==0)&&(keyString[2]==0)&&(keyString[3]==0)))){PORT_Memcpy(&keyTypeStorage,keyString,sizeof(keyTypeStorage));keyType=(CK_KEY_TYPE)PR_ntohl(keyTypeStorage);}else{/* * Now Handle: * * Big Endian, pre-3.9, all lengths: 1 (kt) * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0 * -- KeyType == 0 all other cases ---: 4 0 0 0 0 */keyType=(CK_KEY_TYPE)keyString[0];}returnlg_ULongAttribute(attribute,type,keyType);caseCKA_VALUE:returnlg_CopyPrivAttribute(attribute,type,key->u.rsa.privateExponent.data,key->u.rsa.privateExponent.len,obj->sdb);caseCKA_VALUE_LEN:keyLen=key->u.rsa.privateExponent.len;returnlg_ULongAttribute(attribute,type,keyLen);}returnlg_invalidAttribute(attribute);}staticCK_RVlg_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey*key,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute,SDB*sdbpw){unsignedcharhash[SHA1_LENGTH];CK_KEY_TYPEkeyType=CKK_RSA;switch(type){caseCKA_KEY_TYPE:returnlg_ULongAttribute(attribute,type,keyType);caseCKA_ID:SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);returnlg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);caseCKA_DERIVE:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_DECRYPT:caseCKA_SIGN:caseCKA_SIGN_RECOVER:caseCKA_UNWRAP:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_MODULUS:returnlg_CopyAttributeSigned(attribute,type,key->u.rsa.modulus.data,key->u.rsa.modulus.len);caseCKA_PUBLIC_EXPONENT:returnlg_CopyAttributeSigned(attribute,type,key->u.rsa.publicExponent.data,key->u.rsa.publicExponent.len);caseCKA_PRIVATE_EXPONENT:returnlg_CopyPrivAttrSigned(attribute,type,key->u.rsa.privateExponent.data,key->u.rsa.privateExponent.len,sdbpw);caseCKA_PRIME_1:returnlg_CopyPrivAttrSigned(attribute,type,key->u.rsa.prime1.data,key->u.rsa.prime1.len,sdbpw);caseCKA_PRIME_2:returnlg_CopyPrivAttrSigned(attribute,type,key->u.rsa.prime2.data,key->u.rsa.prime2.len,sdbpw);caseCKA_EXPONENT_1:returnlg_CopyPrivAttrSigned(attribute,type,key->u.rsa.exponent1.data,key->u.rsa.exponent1.len,sdbpw);caseCKA_EXPONENT_2:returnlg_CopyPrivAttrSigned(attribute,type,key->u.rsa.exponent2.data,key->u.rsa.exponent2.len,sdbpw);caseCKA_COEFFICIENT:returnlg_CopyPrivAttrSigned(attribute,type,key->u.rsa.coefficient.data,key->u.rsa.coefficient.len,sdbpw);default:break;}returnlg_invalidAttribute(attribute);}staticCK_RVlg_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey*key,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute,SDB*sdbpw){unsignedcharhash[SHA1_LENGTH];CK_KEY_TYPEkeyType=CKK_DSA;switch(type){caseCKA_KEY_TYPE:returnlg_ULongAttribute(attribute,type,keyType);caseCKA_ID:SHA1_HashBuf(hash,key->u.dsa.publicValue.data,key->u.dsa.publicValue.len);returnlg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);caseCKA_DERIVE:caseCKA_DECRYPT:caseCKA_SIGN_RECOVER:caseCKA_UNWRAP:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_SIGN:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_VALUE:returnlg_CopyPrivAttrSigned(attribute,type,key->u.dsa.privateValue.data,key->u.dsa.privateValue.len,sdbpw);caseCKA_PRIME:returnlg_CopyAttributeSigned(attribute,type,key->u.dsa.params.prime.data,key->u.dsa.params.prime.len);caseCKA_SUBPRIME:returnlg_CopyAttributeSigned(attribute,type,key->u.dsa.params.subPrime.data,key->u.dsa.params.subPrime.len);caseCKA_BASE:returnlg_CopyAttributeSigned(attribute,type,key->u.dsa.params.base.data,key->u.dsa.params.base.len);caseCKA_NETSCAPE_DB:returnlg_CopyAttributeSigned(attribute,type,key->u.dsa.publicValue.data,key->u.dsa.publicValue.len);default:break;}returnlg_invalidAttribute(attribute);}staticCK_RVlg_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey*key,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute,SDB*sdbpw){unsignedcharhash[SHA1_LENGTH];CK_KEY_TYPEkeyType=CKK_DH;switch(type){caseCKA_KEY_TYPE:returnlg_ULongAttribute(attribute,type,keyType);caseCKA_ID:SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);returnlg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);caseCKA_DERIVE:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_DECRYPT:caseCKA_SIGN:caseCKA_SIGN_RECOVER:caseCKA_UNWRAP:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_VALUE:returnlg_CopyPrivAttrSigned(attribute,type,key->u.dh.privateValue.data,key->u.dh.privateValue.len,sdbpw);caseCKA_PRIME:returnlg_CopyAttributeSigned(attribute,type,key->u.dh.prime.data,key->u.dh.prime.len);caseCKA_BASE:returnlg_CopyAttributeSigned(attribute,type,key->u.dh.base.data,key->u.dh.base.len);caseCKA_NETSCAPE_DB:returnlg_CopyAttributeSigned(attribute,type,key->u.dh.publicValue.data,key->u.dh.publicValue.len);default:break;}returnlg_invalidAttribute(attribute);}#ifndef NSS_DISABLE_ECCstaticCK_RVlg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey*key,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute,SDB*sdbpw){unsignedcharhash[SHA1_LENGTH];CK_KEY_TYPEkeyType=CKK_EC;switch(type){caseCKA_KEY_TYPE:returnlg_ULongAttribute(attribute,type,keyType);caseCKA_ID:SHA1_HashBuf(hash,key->u.ec.publicValue.data,key->u.ec.publicValue.len);returnlg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);caseCKA_DERIVE:caseCKA_SIGN:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_DECRYPT:caseCKA_SIGN_RECOVER:caseCKA_UNWRAP:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_VALUE:returnlg_CopyPrivAttrSigned(attribute,type,key->u.ec.privateValue.data,key->u.ec.privateValue.len,sdbpw);caseCKA_EC_PARAMS:returnlg_CopyAttributeSigned(attribute,type,key->u.ec.ecParams.DEREncoding.data,key->u.ec.ecParams.DEREncoding.len);caseCKA_NETSCAPE_DB:returnlg_CopyAttributeSigned(attribute,type,key->u.ec.publicValue.data,key->u.ec.publicValue.len);default:break;}returnlg_invalidAttribute(attribute);}#endif /* NSS_DISABLE_ECC */staticCK_RVlg_FindPrivateKeyAttribute(LGObjectCache*obj,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute){NSSLOWKEYPrivateKey*key;char*label;CK_RVcrv;switch(type){caseCKA_PRIVATE:caseCKA_SENSITIVE:caseCKA_ALWAYS_SENSITIVE:caseCKA_EXTRACTABLE:caseCKA_MODIFIABLE:caseCKA_LOCAL:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_NEVER_EXTRACTABLE:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_SUBJECT:returnLG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);caseCKA_START_DATE:caseCKA_END_DATE:returnLG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);caseCKA_LABEL:label=lg_FindKeyNicknameByPublicKey(obj->sdb,&obj->dbKey);if(label==NULL){returnLG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);}crv=lg_CopyAttribute(attribute,type,label,PORT_Strlen(label));PORT_Free(label);returncrv;default:break;}key=lg_GetPrivateKey(obj);if(key==NULL){returnCKR_OBJECT_HANDLE_INVALID;}switch(key->keyType){caseNSSLOWKEYRSAKey:returnlg_FindRSAPrivateKeyAttribute(key,type,attribute,obj->sdb);caseNSSLOWKEYDSAKey:returnlg_FindDSAPrivateKeyAttribute(key,type,attribute,obj->sdb);caseNSSLOWKEYDHKey:returnlg_FindDHPrivateKeyAttribute(key,type,attribute,obj->sdb);#ifndef NSS_DISABLE_ECCcaseNSSLOWKEYECKey:returnlg_FindECPrivateKeyAttribute(key,type,attribute,obj->sdb);#endif /* NSS_DISABLE_ECC */default:break;}returnlg_invalidAttribute(attribute);}staticCK_RVlg_FindSMIMEAttribute(LGObjectCache*obj,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute){certDBEntrySMime*entry;switch(type){caseCKA_PRIVATE:caseCKA_MODIFIABLE:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_NSS_EMAIL:returnlg_CopyAttribute(attribute,type,obj->dbKey.data,obj->dbKey.len-1);caseCKA_NSS_SMIME_TIMESTAMP:caseCKA_SUBJECT:caseCKA_VALUE:break;default:returnlg_invalidAttribute(attribute);}entry=lg_getSMime(obj);if(entry==NULL){returnCKR_OBJECT_HANDLE_INVALID;}switch(type){caseCKA_NSS_SMIME_TIMESTAMP:returnlg_CopyAttribute(attribute,type,entry->optionsDate.data,entry->optionsDate.len);caseCKA_SUBJECT:returnlg_CopyAttribute(attribute,type,entry->subjectName.data,entry->subjectName.len);caseCKA_VALUE:returnlg_CopyAttribute(attribute,type,entry->smimeOptions.data,entry->smimeOptions.len);default:break;}returnlg_invalidAttribute(attribute);}staticCK_RVlg_FindTrustAttribute(LGObjectCache*obj,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute){NSSLOWCERTTrust*trust;NSSLOWCERTCertDBHandle*certHandle;NSSLOWCERTCertificate*cert;unsignedcharhash[SHA1_LENGTH];unsignedinttrustFlags;CK_RVcrv;switch(type){caseCKA_PRIVATE:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_MODIFIABLE:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_CERT_SHA1_HASH:caseCKA_CERT_MD5_HASH:caseCKA_TRUST_CLIENT_AUTH:caseCKA_TRUST_SERVER_AUTH:caseCKA_TRUST_EMAIL_PROTECTION:caseCKA_TRUST_CODE_SIGNING:caseCKA_TRUST_STEP_UP_APPROVED:caseCKA_ISSUER:caseCKA_SERIAL_NUMBER:break;default:returnlg_invalidAttribute(attribute);}certHandle=lg_getCertDB(obj->sdb);if(!certHandle){returnCKR_OBJECT_HANDLE_INVALID;}trust=lg_getTrust(obj,certHandle);if(trust==NULL){returnCKR_OBJECT_HANDLE_INVALID;}switch(type){caseCKA_CERT_SHA1_HASH:SHA1_HashBuf(hash,trust->derCert->data,trust->derCert->len);returnlg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);caseCKA_CERT_MD5_HASH:MD5_HashBuf(hash,trust->derCert->data,trust->derCert->len);returnlg_CopyAttribute(attribute,type,hash,MD5_LENGTH);caseCKA_TRUST_CLIENT_AUTH:trustFlags=trust->trust->sslFlags&CERTDB_TRUSTED_CLIENT_CA?trust->trust->sslFlags|CERTDB_TRUSTED_CA:0;gototrust;caseCKA_TRUST_SERVER_AUTH:trustFlags=trust->trust->sslFlags;gototrust;caseCKA_TRUST_EMAIL_PROTECTION:trustFlags=trust->trust->emailFlags;gototrust;caseCKA_TRUST_CODE_SIGNING:trustFlags=trust->trust->objectSigningFlags;trust:if(trustFlags&CERTDB_TRUSTED_CA){returnlg_ULongAttribute(attribute,type,CKT_NSS_TRUSTED_DELEGATOR);}if(trustFlags&CERTDB_TRUSTED){returnlg_ULongAttribute(attribute,type,CKT_NSS_TRUSTED);}if(trustFlags&CERTDB_MUST_VERIFY){returnlg_ULongAttribute(attribute,type,CKT_NSS_MUST_VERIFY_TRUST);}if(trustFlags&CERTDB_TRUSTED_UNKNOWN){returnlg_ULongAttribute(attribute,type,CKT_NSS_TRUST_UNKNOWN);}if(trustFlags&CERTDB_VALID_CA){returnlg_ULongAttribute(attribute,type,CKT_NSS_VALID_DELEGATOR);}if(trustFlags&CERTDB_TERMINAL_RECORD){returnlg_ULongAttribute(attribute,type,CKT_NSS_NOT_TRUSTED);}returnlg_ULongAttribute(attribute,type,CKT_NSS_TRUST_UNKNOWN);caseCKA_TRUST_STEP_UP_APPROVED:if(trust->trust->sslFlags&CERTDB_GOVT_APPROVED_CA){returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);}else{returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);}default:break;}switch(type){caseCKA_ISSUER:cert=lg_getCert(obj,certHandle);if(cert==NULL)break;crv=lg_CopyAttribute(attribute,type,cert->derIssuer.data,cert->derIssuer.len);break;caseCKA_SERIAL_NUMBER:cert=lg_getCert(obj,certHandle);if(cert==NULL)break;crv=lg_CopyAttribute(attribute,type,cert->derSN.data,cert->derSN.len);break;default:cert=NULL;break;}if(cert){nsslowcert_DestroyCertificate(cert);returncrv;}returnlg_invalidAttribute(attribute);}staticCK_RVlg_FindCrlAttribute(LGObjectCache*obj,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute){certDBEntryRevocation*crl;switch(type){caseCKA_PRIVATE:caseCKA_MODIFIABLE:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_NSS_KRL:return((obj->handle==LG_TOKEN_KRL_HANDLE)?LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr):LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr));caseCKA_SUBJECT:returnlg_CopyAttribute(attribute,type,obj->dbKey.data,obj->dbKey.len);caseCKA_NSS_URL:caseCKA_VALUE:break;default:returnlg_invalidAttribute(attribute);}crl=lg_getCrl(obj);if(!crl){returnCKR_OBJECT_HANDLE_INVALID;}switch(type){caseCKA_NSS_URL:if(crl->url==NULL){returnLG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);}returnlg_CopyAttribute(attribute,type,crl->url,PORT_Strlen(crl->url)+1);caseCKA_VALUE:returnlg_CopyAttribute(attribute,type,crl->derCrl.data,crl->derCrl.len);default:break;}returnlg_invalidAttribute(attribute);}staticCK_RVlg_FindCertAttribute(LGObjectCache*obj,CK_ATTRIBUTE_TYPEtype,CK_ATTRIBUTE*attribute){NSSLOWCERTCertificate*cert;NSSLOWCERTCertDBHandle*certHandle;NSSLOWKEYPublicKey*pubKey;unsignedcharhash[SHA1_LENGTH];SECItem*item;switch(type){caseCKA_PRIVATE:returnLG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);caseCKA_MODIFIABLE:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_CERTIFICATE_TYPE:/* hardcoding X.509 into here */returnlg_ULongAttribute(attribute,type,CKC_X_509);caseCKA_VALUE:caseCKA_ID:caseCKA_LABEL:caseCKA_SUBJECT:caseCKA_ISSUER:caseCKA_SERIAL_NUMBER:caseCKA_NSS_EMAIL:break;default:returnlg_invalidAttribute(attribute);}certHandle=lg_getCertDB(obj->sdb);if(certHandle==NULL){returnCKR_OBJECT_HANDLE_INVALID;}cert=lg_getCert(obj,certHandle);if(cert==NULL){returnCKR_OBJECT_HANDLE_INVALID;}switch(type){caseCKA_VALUE:returnlg_CopyAttribute(attribute,type,cert->derCert.data,cert->derCert.len);caseCKA_ID:if(((cert->trust->sslFlags&CERTDB_USER)==0)&&((cert->trust->emailFlags&CERTDB_USER)==0)&&((cert->trust->objectSigningFlags&CERTDB_USER)==0)){returnLG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);}pubKey=nsslowcert_ExtractPublicKey(cert);if(pubKey==NULL)break;item=lg_GetPubItem(pubKey);if(item==NULL){lg_nsslowkey_DestroyPublicKey(pubKey);break;}SHA1_HashBuf(hash,item->data,item->len);/* item is imbedded in pubKey, just free the key */lg_nsslowkey_DestroyPublicKey(pubKey);returnlg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);caseCKA_LABEL:returncert->nickname?lg_CopyAttribute(attribute,type,cert->nickname,PORT_Strlen(cert->nickname)):LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);caseCKA_SUBJECT:returnlg_CopyAttribute(attribute,type,cert->derSubject.data,cert->derSubject.len);caseCKA_ISSUER:returnlg_CopyAttribute(attribute,type,cert->derIssuer.data,cert->derIssuer.len);caseCKA_SERIAL_NUMBER:returnlg_CopyAttribute(attribute,type,cert->derSN.data,cert->derSN.len);caseCKA_NSS_EMAIL:return(cert->emailAddr&&cert->emailAddr[0])?lg_CopyAttribute(attribute,type,cert->emailAddr,PORT_Strlen(cert->emailAddr)):LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);default:break;}returnlg_invalidAttribute(attribute);}CK_RVlg_GetSingleAttribute(LGObjectCache*obj,CK_ATTRIBUTE*attribute){/* handle the common ones */CK_ATTRIBUTE_TYPEtype=attribute->type;switch(type){caseCKA_CLASS:returnlg_ULongAttribute(attribute,type,obj->objclass);caseCKA_TOKEN:returnLG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);caseCKA_LABEL:if((obj->objclass==CKO_CERTIFICATE)||(obj->objclass==CKO_PRIVATE_KEY)||(obj->objclass==CKO_PUBLIC_KEY)||(obj->objclass==CKO_SECRET_KEY)){break;}returnLG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);default:break;}switch(obj->objclass){caseCKO_CERTIFICATE:returnlg_FindCertAttribute(obj,type,attribute);caseCKO_NSS_CRL:returnlg_FindCrlAttribute(obj,type,attribute);caseCKO_NSS_TRUST:returnlg_FindTrustAttribute(obj,type,attribute);caseCKO_NSS_SMIME:returnlg_FindSMIMEAttribute(obj,type,attribute);caseCKO_PUBLIC_KEY:returnlg_FindPublicKeyAttribute(obj,type,attribute);caseCKO_PRIVATE_KEY:returnlg_FindPrivateKeyAttribute(obj,type,attribute);caseCKO_SECRET_KEY:returnlg_FindSecretKeyAttribute(obj,type,attribute);default:break;}returnlg_invalidAttribute(attribute);}/* * Fill in the attribute template based on the data in the database. */CK_RVlg_GetAttributeValue(SDB*sdb,CK_OBJECT_HANDLEhandle,CK_ATTRIBUTE*templ,CK_ULONGcount){LGObjectCache*obj=lg_NewObjectCache(sdb,NULL,handle&~LG_TOKEN_MASK);CK_RVcrv,crvCollect=CKR_OK;unsignedinti;if(obj==NULL){returnCKR_OBJECT_HANDLE_INVALID;}for(i=0;i<count;i++){crv=lg_GetSingleAttribute(obj,&templ[i]);if(crvCollect==CKR_OK)crvCollect=crv;}lg_DestroyObjectCache(obj);returncrvCollect;}PRBoollg_cmpAttribute(LGObjectCache*obj,constCK_ATTRIBUTE*attribute){unsignedcharbuf[LG_BUF_SPACE];CK_ATTRIBUTEtestAttr;unsignedchar*tempBuf=NULL;PRBoolmatch=PR_TRUE;CK_RVcrv;/* we're going to compare 'attribute' with the actual attribute from * the object. We'll use the length of 'attribute' to decide how much * space we need to read the test attribute. If 'attribute' doesn't give * enough space, then we know the values don't match and that will * show up as ckr != CKR_OK */testAttr=*attribute;testAttr.pValue=buf;/* if we don't have enough space, malloc it */if(attribute->ulValueLen>LG_BUF_SPACE){tempBuf=PORT_Alloc(attribute->ulValueLen);if(!tempBuf){returnPR_FALSE;}testAttr.pValue=tempBuf;}/* get the attribute */crv=lg_GetSingleAttribute(obj,&testAttr);/* if the attribute was read OK, compare it */if((crv!=CKR_OK)||(attribute->pValue==NULL)||(attribute->ulValueLen!=testAttr.ulValueLen)||(PORT_Memcmp(attribute->pValue,testAttr.pValue,testAttr.ulValueLen)!=0)){/* something didn't match, this isn't the object we are looking for */match=PR_FALSE;}/* free the buffer we may have allocated */if(tempBuf){PORT_Free(tempBuf);}returnmatch;}PRBoollg_tokenMatch(SDB*sdb,constSECItem*dbKey,CK_OBJECT_HANDLEclass,constCK_ATTRIBUTE*templ,CK_ULONGcount){PRBoolmatch=PR_TRUE;LGObjectCache*obj=lg_NewObjectCache(sdb,dbKey,class);unsignedinti;if(obj==NULL){returnPR_FALSE;}for(i=0;i<count;i++){match=lg_cmpAttribute(obj,&templ[i]);if(!match){break;}}/* done looking, free up our cache */lg_DestroyObjectCache(obj);/* if we get through the whole list without finding a mismatched attribute, * then this object fits the criteria we are matching */returnmatch;}staticCK_RVlg_SetCertAttribute(LGObjectCache*obj,CK_ATTRIBUTE_TYPEtype,constvoid*value,unsignedintlen){NSSLOWCERTCertificate*cert;NSSLOWCERTCertDBHandle*certHandle;char*nickname=NULL;SECStatusrv;CK_RVcrv;/* we can't change the EMAIL values, but let the * upper layers feel better about the fact we tried to set these */if(type==CKA_NSS_EMAIL){returnCKR_OK;}certHandle=lg_getCertDB(obj->sdb);if(certHandle==NULL){crv=CKR_TOKEN_WRITE_PROTECTED;gotodone;}if((type!=CKA_LABEL)&&(type!=CKA_ID)){crv=CKR_ATTRIBUTE_READ_ONLY;gotodone;}cert=lg_getCert(obj,certHandle);if(cert==NULL){crv=CKR_OBJECT_HANDLE_INVALID;gotodone;}/* if the app is trying to set CKA_ID, it's probably because it just * imported the key. Look to see if we need to set the CERTDB_USER bits. */if(type==CKA_ID){if(((cert->trust->sslFlags&CERTDB_USER)==0)&&((cert->trust->emailFlags&CERTDB_USER)==0)&&((cert->trust->objectSigningFlags&CERTDB_USER)==0)){NSSLOWKEYDBHandle*keyHandle;keyHandle=lg_getKeyDB(obj->sdb);if(keyHandle){if(nsslowkey_KeyForCertExists(keyHandle,cert)){NSSLOWCERTCertTrusttrust=*cert->trust;trust.sslFlags|=CERTDB_USER;trust.emailFlags|=CERTDB_USER;trust.objectSigningFlags|=CERTDB_USER;nsslowcert_ChangeCertTrust(certHandle,cert,&trust);}}}crv=CKR_OK;gotodone;}/* must be CKA_LABEL */if(value!=NULL){nickname=PORT_ZAlloc(len+1);if(nickname==NULL){crv=CKR_HOST_MEMORY;gotodone;}PORT_Memcpy(nickname,value,len);nickname[len]=0;}rv=nsslowcert_AddPermNickname(certHandle,cert,nickname);crv=(rv==SECSuccess)?CKR_OK:CKR_DEVICE_ERROR;done:if(nickname){PORT_Free(nickname);}returncrv;}staticCK_RVlg_SetPrivateKeyAttribute(LGObjectCache*obj,CK_ATTRIBUTE_TYPEtype,constvoid*value,unsignedintlen,PRBool*writePrivate){NSSLOWKEYPrivateKey*privKey;NSSLOWKEYDBHandle*keyHandle;char*nickname=NULL;SECStatusrv;CK_RVcrv;/* we can't change the ID and we don't store the subject, but let the * upper layers feel better about the fact we tried to set these */if((type==CKA_ID)||(type==CKA_SUBJECT)||(type==CKA_LOCAL)||(type==CKA_NEVER_EXTRACTABLE)||(type==CKA_ALWAYS_SENSITIVE)){returnCKR_OK;}keyHandle=lg_getKeyDB(obj->sdb);if(keyHandle==NULL){crv=CKR_TOKEN_WRITE_PROTECTED;gotodone;}privKey=lg_GetPrivateKeyWithDB(obj,keyHandle);if(privKey==NULL){crv=CKR_OBJECT_HANDLE_INVALID;gotodone;}crv=CKR_ATTRIBUTE_READ_ONLY;switch(type){caseCKA_LABEL:if(value!=NULL){nickname=PORT_ZAlloc(len+1);if(nickname==NULL){crv=CKR_HOST_MEMORY;gotodone;}PORT_Memcpy(nickname,value,len);nickname[len]=0;}rv=nsslowkey_UpdateNickname(keyHandle,privKey,&obj->dbKey,nickname,obj->sdb);crv=(rv==SECSuccess)?CKR_OK:CKR_DEVICE_ERROR;break;caseCKA_UNWRAP:caseCKA_SIGN:caseCKA_DERIVE:caseCKA_SIGN_RECOVER:caseCKA_DECRYPT:/* ignore attempts to change restrict these. * legacyDB ignore these flags and always presents all of them * that are valid as true. * NOTE: We only get here if the current value and the new value do * not match. */if(*(char*)value==0){crv=CKR_OK;}break;caseCKA_VALUE:caseCKA_PRIVATE_EXPONENT:caseCKA_PRIME_1:caseCKA_PRIME_2:caseCKA_EXPONENT_1:caseCKA_EXPONENT_2:caseCKA_COEFFICIENT:/* We aren't really changing these values, we are just triggering * the database to update it's entry */*writePrivate=PR_TRUE;crv=CKR_OK;break;default:crv=CKR_ATTRIBUTE_READ_ONLY;break;}done:if(nickname){PORT_Free(nickname);}returncrv;}staticCK_RVlg_SetPublicKeyAttribute(LGObjectCache*obj,CK_ATTRIBUTE_TYPEtype,constvoid*value,unsignedintlen,PRBool*writePrivate){/* we can't change the ID and we don't store the subject, but let the * upper layers feel better about the fact we tried to set these */if((type==CKA_ID)||(type==CKA_SUBJECT)||(type==CKA_LABEL)){returnCKR_OK;}returnCKR_ATTRIBUTE_READ_ONLY;}staticCK_RVlg_SetTrustAttribute(LGObjectCache*obj,constCK_ATTRIBUTE*attr){unsignedintflags;CK_TRUSTtrust;NSSLOWCERTCertificate*cert=NULL;NSSLOWCERTCertDBHandle*certHandle;NSSLOWCERTCertTrustdbTrust;SECStatusrv;CK_RVcrv;if(attr->type==CKA_LABEL){returnCKR_OK;}crv=lg_GetULongAttribute(attr->type,attr,1,&trust);if(crv!=CKR_OK){returncrv;}flags=lg_MapTrust(trust,(PRBool)(attr->type==CKA_TRUST_CLIENT_AUTH));certHandle=lg_getCertDB(obj->sdb);if(certHandle==NULL){crv=CKR_TOKEN_WRITE_PROTECTED;gotodone;}cert=lg_getCert(obj,certHandle);if(cert==NULL){crv=CKR_OBJECT_HANDLE_INVALID;gotodone;}dbTrust=*cert->trust;switch(attr->type){caseCKA_TRUST_EMAIL_PROTECTION:dbTrust.emailFlags=flags|(cert->trust->emailFlags&CERTDB_PRESERVE_TRUST_BITS);break;caseCKA_TRUST_CODE_SIGNING:dbTrust.objectSigningFlags=flags|(cert->trust->objectSigningFlags&CERTDB_PRESERVE_TRUST_BITS);break;caseCKA_TRUST_CLIENT_AUTH:dbTrust.sslFlags=flags|(cert->trust->sslFlags&(CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CA));break;caseCKA_TRUST_SERVER_AUTH:dbTrust.sslFlags=flags|(cert->trust->sslFlags&(CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CLIENT_CA));break;default:crv=CKR_ATTRIBUTE_READ_ONLY;gotodone;}rv=nsslowcert_ChangeCertTrust(certHandle,cert,&dbTrust);crv=(rv==SECSuccess)?CKR_OK:CKR_DEVICE_ERROR;done:if(cert){nsslowcert_DestroyCertificate(cert);}returncrv;}staticCK_RVlg_SetSingleAttribute(LGObjectCache*obj,constCK_ATTRIBUTE*attr,PRBool*writePrivate){CK_ATTRIBUTEattribLocal;CK_RVcrv;if((attr->type==CKA_NETSCAPE_DB)&&(obj->objclass==CKO_PRIVATE_KEY)){*writePrivate=PR_TRUE;returnCKR_OK;}/* Make sure the attribute exists first */attribLocal.type=attr->type;attribLocal.pValue=NULL;attribLocal.ulValueLen=0;crv=lg_GetSingleAttribute(obj,&attribLocal);if(crv!=CKR_OK){returncrv;}/* if we are just setting it to the value we already have, * allow it to happen. Let label setting go through so * we have the opportunity to repair any database corruption. */if(attr->type!=CKA_LABEL){if(lg_cmpAttribute(obj,attr)){returnCKR_OK;}}crv=CKR_ATTRIBUTE_READ_ONLY;switch(obj->objclass){caseCKO_CERTIFICATE:/* change NICKNAME, EMAIL, */crv=lg_SetCertAttribute(obj,attr->type,attr->pValue,attr->ulValueLen);break;caseCKO_NSS_CRL:/* change URL */break;caseCKO_NSS_TRUST:crv=lg_SetTrustAttribute(obj,attr);break;caseCKO_PRIVATE_KEY:caseCKO_SECRET_KEY:crv=lg_SetPrivateKeyAttribute(obj,attr->type,attr->pValue,attr->ulValueLen,writePrivate);break;caseCKO_PUBLIC_KEY:crv=lg_SetPublicKeyAttribute(obj,attr->type,attr->pValue,attr->ulValueLen,writePrivate);break;}returncrv;}/* * Fill in the attribute template based on the data in the database. */CK_RVlg_SetAttributeValue(SDB*sdb,CK_OBJECT_HANDLEhandle,constCK_ATTRIBUTE*templ,CK_ULONGcount){LGObjectCache*obj=lg_NewObjectCache(sdb,NULL,handle&~LG_TOKEN_MASK);CK_RVcrv,crvCollect=CKR_OK;PRBoolwritePrivate=PR_FALSE;unsignedinti;if(obj==NULL){returnCKR_OBJECT_HANDLE_INVALID;}for(i=0;i<count;i++){crv=lg_SetSingleAttribute(obj,&templ[i],&writePrivate);if(crvCollect==CKR_OK)crvCollect=crv;}/* Write any collected changes out for private and secret keys. * don't do the write for just the label */if(writePrivate){NSSLOWKEYPrivateKey*privKey=lg_GetPrivateKey(obj);SECStatusrv=SECFailure;char*label=lg_FindKeyNicknameByPublicKey(obj->sdb,&obj->dbKey);if(privKey){rv=nsslowkey_StoreKeyByPublicKeyAlg(lg_getKeyDB(sdb),privKey,&obj->dbKey,label,sdb,PR_TRUE);}if(rv!=SECSuccess){crv=CKR_DEVICE_ERROR;}PORT_Free(label);}lg_DestroyObjectCache(obj);returncrvCollect;}